/*
 * File:    DocumentBuilderPool.java
 * Created: 05-Feb-2009
 * Version: $Id$
 *
 * COPYRIGHT (C) 2009, Bitgate Mobile, LLC.  All Rights Reserved.
 *
 * software@bitgatemobile.com
 */

package com.webplasm.render.engine;

import static com.bitgate.util.debug.Debug.crit;
import static com.bitgate.util.debug.Debug.debug;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

/**
 * This class is used to pool a set of available <code>DocumentBuilder</code> objects so that XML documents can be
 * parsed into objects.  Because the system generally parses documents one at a time and blocks on subsequent calls
 * to other documents, the pool makes it possible to render multiple documents without the slowness.  However, this
 * anomaly could be accelerated if the system receives multiple web requests per second, and the pool is overloaded.
 * 
 * @author kenji
 * @since Webplasm 1.0
 */
public class DocumentBuilderPool {
	private static final DocumentBuilderPool _default = new DocumentBuilderPool();
    private static DocumentBuilderFactory factory;
    private static DocumentBuilder[] builder;
    private static int builderPosition;
    private static final int DEFAULT_PARSER_POOLS = 10;
    
    static {
    	factory = DocumentBuilderFactory.newInstance();
    	factory.setValidating(false);
    	
    	builderPosition = 0;
    	int numBuilders = DEFAULT_PARSER_POOLS;
    	
    	debug("Starting " + numBuilders + " rendering objects.");
    	
    	builder = new DocumentBuilder[(numBuilders + 1)];
    	
    	for(int i = 0; i < (numBuilders + 1); i++) {
    		try {
    			builder[i] = factory.newDocumentBuilder();
//    			builder[i].setErrorHandler(new SAXErrorHandler("internal"));
    		} catch(ParserConfigurationException e) {
    			crit("Unable to instantiate a new document builder object: " + e.getMessage());
    		}
    	}
    }
    
    /**
     * Retrieves the next builder object.
     * 
     * @return <code>DocumentBuilder</code> object.
     */
    public DocumentBuilder getBuilder() {
    	if (builderPosition >= builder.length) {
    		builderPosition = 0;
    	}
    	
    	return builder[builderPosition++];
    }
    
    /**
     * Returns the default instance of this singleton class.
     * 
     * @return <code>DocumentBuilderPool</code> object.
     */
    public static final DocumentBuilderPool getDefault() {
    	return _default;
    }
    
    /**
     * Returns the <code>DocumentBuilderFactory</code> object that was used, if a <code>DocumentBuilder</code> needs
     * to be instantiated by hand.
     * 
     * @return <code>DocumentBuilderFactory</code> object.
     */
    public static final DocumentBuilderFactory getFactory() {
    	return factory;
    }
}